/*
 * BitArray.c
 *
 *  Created on: 12/02/2012
 *      Author: marcio
 */

#include "BitArray.h"
#include <stdlib.h>

BitArray* bitarray_newBitArray(int size){
	BitArray* a = malloc(sizeof(BitArray));
	a->vectorsz = ((size >> 3)<<3) == size ? size >> 3 : size >> 3 + 1;
	a->elem = malloc(sizeof(char)*a->vectorsz);
	a->size = size;
}

int bitarray_setbit(BitArray* a, int i){
	return a->elem[i >> 3] |= (1LL << (i & ((1LL << 3) - 1)));
}

int bitarray_unsetbit(BitArray* a, int i){
	return a->elem[i >> 3] &= ~(1LL << (i & ((1LL << 3) - 1)));
}

int bitarray_isset(BitArray* a, int i){
	return a->elem[i >> 3] & ~(1LL << (i & ((1LL << 3) - 1)));
}

BitArray* bitarray_and(BitArray* a, BitArray* b){
	int i;
	int minsize = a->size > b->size? a->size : b->size;
	BitArray* c = bitarray_newBitArray(minsize);
	for(i = 0; i < c->vectorsz; i++){
		c->elem[i] = a->elem[i] & b->elem[i];
	}
	return c;
}

BitArray* bitarray_or(BitArray* a, BitArray* b){
	int i;
	int minsize = a->size > b->size? a->size : b->size;
	BitArray* c = bitarray_newBitArray(minsize);
	for(i = 0; i < c->vectorsz; i++){
		c->elem[i] = a->elem[i] | b->elem[i];
	}
	return c;
}

BitArray* bitarray_exclusiveOr(BitArray* a, BitArray* b){
	int i;
	int minsize = a->size > b->size? a->size : b->size;
	BitArray* c = bitarray_newBitArray(minsize);
	for(i = 0; i < c->vectorsz; i++){
		c->elem[i] = a->elem[i] ^ b->elem[i];
	}
	return c;
}

int bitarray_count1(BitArray* a){
	int i;
	int ret = 0;
	for(i =0; i < a->vectorsz; i++){
		ret += __builtin_popcount(a->elem[i]);
	}
	return ret;
}

int bitarray_count0(BitArray* a){
	return a->size - bitarray_count1(a);
}

BitArray* bitarray_not(BitArray* a){
	int i;
	BitArray* c = bitarray_newBitArray(a->size);
	for(i = 0; i < a->vectorsz; i++){
		c->elem[i] = ~(a->elem[i]);
	}
	return c;
}

BitArray* bitarray_nand(BitArray* a, BitArray* b){
	int i;
	int minsize = a->size > b->size? a->size : b->size;
	BitArray* c = bitarray_newBitArray(minsize);
	for(i = 0; i < c->vectorsz; i++){
		c->elem[i] = ~(a->elem[i] & b->elem[i]);
	}
	return c;
}

BitArray* bitarray_nor(BitArray* a, BitArray* b){
	int i;
	int minsize = a->size > b->size? a->size : b->size;
	BitArray* c = bitarray_newBitArray(minsize);
	for(i = 0; i < c->vectorsz; i++){
		c->elem[i] = ~(a->elem[i] | b->elem[i]);
	}
	return c;
}

BitArray* bitarray_nexclusiveOr(BitArray* a, BitArray* b){
	int i;
	int minsize = a->size > b->size? a->size : b->size;
	BitArray* c = bitarray_newBitArray(minsize);
	for(i = 0; i < c->vectorsz; i++){
		c->elem[i] = ~(a->elem[i] ^ b->elem[i]);
	}
	return c;
}

void bitarray_andRef(BitArray* a, BitArray* b){
	int i;
	int minsize = a->vectorsz > b->vectorsz? a->vectorsz : b->vectorsz;
	for(i = 0; i < minsize; i++){
		a->elem[i] &= b->elem[i];
	}
}

void bitarray_orRef(BitArray* a, BitArray* b){
	int i;
	int minsize = a->vectorsz > b->vectorsz? a->vectorsz : b->vectorsz;
	for(i = 0; i < minsize; i++){
		a->elem[i] |= b->elem[i];
	}
}

void bitarray_exclusiveOrRef(BitArray* a, BitArray* b){
	int i;
	int minsize = a->vectorsz > b->vectorsz? a->vectorsz : b->vectorsz;
	for(i = 0; i < minsize; i++){
		a->elem[i] ^= b->elem[i];
	}
}

BitArray* bitarray_notRef(BitArray* a){
	int i;
	for(i = 0; i < a->vectorsz; i++){
		a->elem[i] = ~(a->elem[i]);
	}
}

BitArray* bitarray_nandRef(BitArray* a, BitArray* b){
	int i;
	int minsize = a->vectorsz > b->vectorsz? a->vectorsz : b->vectorsz;
	for(i = 0; i < minsize; i++){
		a->elem[i] = ~(a->elem & b->elem[i]);
	}
}

BitArray* bitarray_norRef(BitArray* a, BitArray* b){
	int i;
	int minsize = a->vectorsz > b->vectorsz? a->vectorsz : b->vectorsz;
	for(i = 0; i < minsize; i++){
		a->elem[i] = ~(a->elem | b->elem[i]);
	}
}

BitArray* bitarray_nexclusiveOrRef(BitArray* a, BitArray* b){
	int i;
	int minsize = a->vectorsz > b->vectorsz? a->vectorsz : b->vectorsz;
	for(i = 0; i < minsize; i++){
		a->elem[i] = ~(a->elem ^ b->elem[i]);
	}
}

int bitarray_delete(BitArray* a){
	free(a->elem);
	free(a);
}
